package com.xucia.strands.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.net.URLDecoder;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.xucia.strands.Compiler;
/**
 * This servlet will automatically compile jss (Strands) and pjs (Persevere Persistent JavaScript) files. The compilation
 * will only be done when a request is made for a file that is changed, in which case it will create a compile
 * and create compiled js file which can be used to fulfill future requests.
 * @author Kris Zyp
 *
 */
public class CompilerServlet extends HttpServlet{
	protected boolean getters = false;
	protected boolean setters = false;
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		downloadCompiled(request, response,null);
		
	}
	/**
	 * 
	 * @param httpRequest
	 * @param response
	 * @return If it compiled and sent the file - false indicates that the default service should be used to download the file
	 * @throws ServletException
	 * @throws IOException
	 */
	public boolean downloadCompiled(HttpServletRequest httpRequest, HttpServletResponse response, Writer writer) throws ServletException, IOException {
		response.setContentType("text/javascript");
		String sourcePath = getSourcePath(httpRequest);
		File sourceFile = new File(sourcePath.replaceAll("\\.js\\z", ".js17"));
		if (!sourceFile.exists())
			sourceFile = new File(sourcePath.replaceAll("\\.js\\z", ".pjs"));
		if (!sourceFile.exists())
			sourceFile = new File(sourcePath.replaceAll("\\.js\\z", ".jss"));
		File jsFile = new File(sourcePath.replaceAll("\\.(pjs)|(jss)|(js17)\\z", ".js"));
		ServletOutputStream os = null;
		if (writer == null)
			os = response.getOutputStream();
		if (sourceFile.exists() && (!jsFile.exists() || sourceFile.lastModified() > jsFile.lastModified())) {
			String output = Compiler.compileFile(sourceFile.getAbsolutePath(),getters,setters,true); // TODO: Need to define the get the setter from the arguments
			new FileOutputStream(jsFile).write(output.getBytes());
			if (writer == null)
				os.print(output);
			else
				writer.write(output);
		}
		else if (jsFile.exists()){
			byte[] b = new byte[4096];
			FileInputStream jsIs = new FileInputStream(jsFile);
			for (int n; (n = jsIs.read(b)) != -1;) {
				if (writer == null)
					os.write(b, 0, n);
				else
					writer.write(new String(b,0,n));
			}
			if (writer == null)
				os.flush();
			else
				writer.flush();
		}
		else {
			response.setStatus(404);
		}
		return true;
	}
	
	protected long getLastModified(HttpServletRequest request) {
		String sourcePath = getSourcePath(request);
		File sourceFile = new File(sourcePath.replaceAll("\\.js\\z", ".js17"));
		if (!sourceFile.exists())
			sourceFile = new File(sourcePath.replaceAll("\\.js\\z", ".pjs"));
		if (!sourceFile.exists())
			sourceFile = new File(sourcePath.replaceAll("\\.js\\z", ".jss"));
		if (sourceFile.exists())
			return sourceFile.lastModified();
		else
			return new File(sourcePath).lastModified();
	}
	private static String getSourcePath(HttpServletRequest httpRequest) {
		String sourcePath = URLDecoder.decode(httpRequest.getRequestURI()).substring(httpRequest.getContextPath().length());
		return httpRequest.getRealPath(sourcePath);
	}

}
